﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include "BurnDlg.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include "BurnCtrl/BurnCtrlFaction.h"
namespace  {
    const int SLEEP_TIME_500 = 500;
}
namespace BurnDlg {

BurnDlg::BurnDlg(QWidget *pParent)
    : QMainWindow(pParent),
      radiobtngrpBoot(1),
      burnCtrl(nullptr),
      setting(nullptr),
      pEvent(nullptr),
      isAutoBurn(false),
      isLoaderDfu(false),
      binModel(nullptr),
      changeChip(nullptr),
      aboutWin(nullptr),
      chipType(ChipType::WIFI5GNB),
      lastWinStates(Qt::WindowNoState),
      isCheckAble(true),
      isEncrypt(false),
      actEnglish(new QAction("English")),
      actChinese(new QAction("中文")),
      menuWifiLanguage(new QMenu(stringClass.GetActionLanguage()))
{
    qRegisterMetaType<LPVOID>("LPVOID");
    qRegisterMetaType<WPARAM>("WPARAM");
    qRegisterMetaType<LPARAM>("LPARAM");
    qRegisterMetaType<long int>("long int");
    QSettings cfg(Global::GetAppConfigPath() + "\\config_all_chip_type.ini", QSettings::IniFormat);
    int translate = cfg.value("AHHCHIPTYPECONFIG/TRANSLATE").toInt();
    if (translate == 0) {
        actEnglish->setCheckable(true);
        actEnglish->setChecked(true);
        actEnglish->setEnabled(true);
        actChinese->setCheckable(false);
        actChinese->setChecked(false);
        actChinese->setEnabled(true);
    } else {
        actEnglish->setCheckable(false);
        actEnglish->setChecked(false);
        actEnglish->setEnabled(true);
        actChinese->setCheckable(true);
        actChinese->setChecked(true);
        actChinese->setEnabled(true);
    }
    if (menuWifiLanguage != nullptr) {
        menuWifiLanguage->addAction(actEnglish);
        menuWifiLanguage->addAction(actChinese);
    }
    connect(actEnglish, &QAction::triggered, this, &BurnDlg::SlotSetEnglish);
    connect(actChinese, &QAction::triggered, this, &BurnDlg::SlotSetChinese);
    burnCtrlManager[0] = nullptr;
    burnCtrlManager[1] = nullptr;
    Global::ReadCfg();
    aboutWin = new AboutWindow();
}

BurnDlg::~BurnDlg()
{
    if (burnCtrl != nullptr) {
        burnCtrl->ClosePort();
        if (burnCtrlManager[0] == burnCtrl) {
            burnCtrlManager[0] = nullptr;
        }
        if (burnCtrlManager[1] == burnCtrl) {
            burnCtrlManager[1] = nullptr;
        }
        delete burnCtrl;
        burnCtrl = nullptr;
    }
    if (burnCtrlManager[0] != nullptr) {
        delete burnCtrlManager[0];
        burnCtrlManager[0] = nullptr;
    }
    if (burnCtrlManager[1] != nullptr) {
        delete burnCtrlManager[1];
        burnCtrlManager[1] = nullptr;
    }
    if (setting != nullptr) {
        delete setting;
        setting = nullptr;
    }
    if (aboutWin != nullptr) {
        delete aboutWin;
        aboutWin = nullptr;
    }
    if (encryptBuffer.bufferData != nullptr) {
        delete [] encryptBuffer.bufferData;
        encryptBuffer.bufferData = nullptr;
    }
    encryptBuffer.bufferLen = 0;
}

void BurnDlg::SlotBnClickedButtonConn()
{
    if (burnCtrl == nullptr) {
        return;
    }
    if (burnCtrl->IsComOpen()) {
        ResetUIAndFSM();
        ReceiveAddText(stringClass.GetIdsString32895());
        return;
    }

    if (!ConfigComPort()) {
        return;
    }
    burnCtrl->SetAutoBurnFlag(isAutoBurn);
    burnCtrl->SetLoaderDfu(isLoaderDfu);
    ReceiveClearText();
    ReceiveAddText(stringClass.GetIdsString32897());
    return;
}

bool BurnDlg::ConfigComPort()
{
    return false;
}

void BurnDlg::SlotBnClickedButtonSelectfile()
{
}

void BurnDlg::SlotBnClickedButtonStartburn()
{
}

void BurnDlg::SlotAutoDisconnect(WPARAM wParam, LPARAM lParam)
{
    Q_UNUSED(wParam);
    Q_UNUSED(lParam);
}

void BurnDlg::SlotInsertPlainText(const QString &editStr)
{
    Q_UNUSED(editStr);
}

void BurnDlg::SlotClearPlainText()
{
}
void BurnDlg::SlotReplacePlainText(const QString &oldText, const QString &newText)
{
    Q_UNUSED(oldText);
    Q_UNUSED(newText);
}

void BurnDlg::SlotMergeCurrentCharFormat(const QTextCharFormat &fmt)
{
    Q_UNUSED(fmt);
}

void BurnDlg::SlotSetProgressValue(unsigned int progress)
{
    Q_UNUSED(progress);
}

void BurnDlg::SlotSetProgressRange(int min, int max)
{
    Q_UNUSED(min);
    Q_UNUSED(max);
}

void BurnDlg::InitBurnCtrl()
{
    if (burnCtrl == nullptr) {
        return;
    }
    BurnCtrlFaction factionBurn;
    burnCtrlManager[0] = factionBurn.GetBurnCtrl(chipType);
    burnCtrl = burnCtrlManager[0];
}

void BurnDlg::ResetUIAndFSM()
{
    if (burnCtrl != nullptr) {
        emit SignalSendMsgInBurnDlg(static_cast<long int>(WiteThreadMsg::WITE_THREAD_MSG_RESETUIANDFSM), 0, 0);
        emit SignalSendMsgInBurnDlg(static_cast<long int>(WiteThreadMsg::WITE_THREAD_MSG_KILLALLTIMER), 0, 0);
        burnCtrl->SetShutDown();
    }
}

void BurnDlg::ReceiveAddText(QString str)
{
    Q_UNUSED(str);
}

void BurnDlg::ReceiveClearText()
{
}

void BurnDlg::SlotShowMenuSettings()
{
    if (burnCtrl == nullptr) {
        return;
    }

    if (setting == nullptr) {
        setting = new DiaglogComSetting(this);
    }
    int burnBaudRate;
    int burnDataBits;
    int burnStopBits;
    QSerialPort::Parity parity;
    int dataFlowCtrl;

    if (setting != nullptr) {
        burnCtrl->GetComSetting(burnBaudRate, burnDataBits, burnStopBits, parity, dataFlowCtrl);
        setting->SetComConfig(burnBaudRate, burnDataBits, burnStopBits, parity, dataFlowCtrl);
        setting->SetForceRead(burnCtrl->GetForceReadFlag());
        setting->SetYModemPackageSize(burnCtrl->GetYModemEachPackageSize());
        setting->SetForceReadTimr(burnCtrl->GetForceReadTime());
        setting->SetCurrentValue();
        connect(setting, &DiaglogComSetting::SignalSettingSuccess, this, &BurnDlg::SlotSettingSuccess);
        setting->show();
    }
}

void BurnDlg::SlotSettingSuccess()
{
    if (burnCtrl == nullptr) {
        return;
    }
    int baud;
    int databits;
    int stopbits;
    QSerialPort::Parity parity;
    int flowctrl;
    if (setting != nullptr) {
        setting->GetComConfig(baud, databits, stopbits, parity, flowctrl);
        burnCtrl->UpdateComSetting(baud, databits, stopbits, parity, flowctrl);
        burnCtrl->SetYModemEachPackageSize(setting->GetYModemPackageSize());
        burnCtrl->SetForceReadFlag(setting->GetForceRead());
        burnCtrl->SetForceReadTime(setting->GetForceReadTime());
    }
}

void BurnDlg::UpdateList()
{
}

void BurnDlg::SlotEarseModeCurrentIndexChanged(int index)
{
    Q_UNUSED(index);
}

void BurnDlg::SlotBnClickedTableHeader(int logicalIndex)
{
    if (!isCheckAble) {
        return;
    }
    if (binModel == nullptr) {
        return;
    }
    if (logicalIndex == 0) {
        QMap<int, bool> mapCheck = binModel->GetMapCheck();
        int i = 0;
        for (; i < mapCheck.size(); i++) {
            if (!(binModel->GetCheck(i))) {
                break;
            }
        }
        if (i == mapCheck.size()) {
            for (int j = 0; j < mapCheck.size(); j++) {
                mapCheck[j] = false;
            }
        } else {
            for (int j = 0; j < mapCheck.size(); j++) {
                mapCheck[j] = true;
            }
        }
        binModel->FetchData(mapCheck);
    }
}

void BurnDlg::SlotBnClickedTableView(const QModelIndex &index)
{
    if (burnCtrl == nullptr || burnCtrl->IsBusy()) {
        QMessageBox::critical(this, stringClass.GetMessageError(),
                              stringClass.GetIdsString32984(), stringClass.GetYes());
        return;
    }
    int nColumn = index.column();
    int nRow = index.row();
    if (nColumn == TABLEVIEW_COLUMN_ADD) {
        QFileDialog fileDialog;
        fileDialog.setWindowTitle(tr("Select File"));
        fileDialog.setDirectory(".");
        fileDialog.setNameFilter(stringClass.GetIdsString32941());
        fileDialog.setFileMode(QFileDialog::ExistingFiles);
        fileDialog.setViewMode(QFileDialog::Detail);
        fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
        if (fileDialog.exec() == QFileDialog::Rejected) {
            return;
        }
        QStringList filePath = fileDialog.selectedFiles();
        if (filePath.size() <= 0) {
            return;
        }
        AnalyseBinFileForOne(filePath[0], nRow);
    } else if (nColumn == TABLEVIEW_COLUMN_DELETE) {
        if (binModel == nullptr) {
            return;
        }
        binModel->removeRows(nRow, 1);
    }
}

void BurnDlg::AnalyseBinFileForOne(QString path, int row)
{
    if (burnCtrl == nullptr || burnCtrl->IsBusy()) {
        QMessageBox::critical(this, stringClass.GetMessageError(),
                              stringClass.GetIdsString32984(), stringClass.GetYes());
        return;
    }
    if (binModel == nullptr) {
        return;
    }
    BIN_INFO_ARRAY infoArray;
    QString version;
    DataConvertor::AnalysMultifBin(path, infoArray, version, isEncrypt, encryptBuffer);
    int infoArraySize = infoArray.GetSize();
    binModel->insertRows(row, infoArraySize);
    QMap<int, BIN_INFO> mapBinInfo = binModel->GetMapBinFileInfo();
    QMap<int, bool> mapCheck = binModel->GetMapCheck();

    for (int i = 0; i < infoArraySize; i++) {
        mapBinInfo[row + i + 1] = infoArray.GetAt(i);
        mapCheck[row + i + 1] = true;
    }
    binModel->FetchData(mapCheck);
    binModel->FetchData(mapBinInfo);
}

void BurnDlg::SlotBnDoubleClickedTableView(const QModelIndex &index)
{
    if (burnCtrl == nullptr || burnCtrl->IsBusy()) {
        QMessageBox::critical(this, stringClass.GetMessageError(),
                              stringClass.GetIdsString32984(), stringClass.GetYes());
        return;
    }
    if (binModel == nullptr) {
        return;
    }
    int nColumn = index.column();
    int nRow = index.row();
    if (nColumn > TABLEVIEW_COLUMN_CHECK && nColumn <= TABLEVIEW_COLUMN_FILE_SIZE) {
        QFileDialog fileDialogDoubleClicked;
        fileDialogDoubleClicked.setWindowTitle(tr("Select File"));
        fileDialogDoubleClicked.setDirectory(".");
        fileDialogDoubleClicked.setNameFilter(stringClass.GetIdsString32949());
        fileDialogDoubleClicked.setFileMode(QFileDialog::ExistingFiles);
        fileDialogDoubleClicked.setViewMode(QFileDialog::Detail);
        fileDialogDoubleClicked.setAcceptMode(QFileDialog::AcceptOpen);
        if (fileDialogDoubleClicked.exec() == QFileDialog::Rejected) {
            return;
        }
        QStringList filePath = fileDialogDoubleClicked.selectedFiles();
        if (filePath.size() <= 0) {
            return;
        }
        BIN_INFO_ARRAY infoArray;
        QString version;
        DataConvertor::AnalysMultifBin(filePath[0], infoArray, version, isEncrypt, encryptBuffer);

        if (infoArray.GetSize() > 1 || infoArray.GetSize() <= 0) {
            return;
        }

        QMap<int, BIN_INFO> mapBinInfo = binModel->GetMapBinFileInfo();
        mapBinInfo[nRow].path = infoArray.GetAt(0).path;
        mapBinInfo[nRow].fileIndex = infoArray.GetAt(0).fileIndex;
        mapBinInfo[nRow].fileSize = infoArray.GetAt(0).fileSize;
        binModel->FetchData(mapBinInfo);
    }
}

void BurnDlg::changeEvent(QEvent* event)
{
    QWidget::changeEvent(event);
}

void BurnDlg::SlotShowChangeChip()
{
    changeChip = new ChangeChip(this);
    if (changeChip != nullptr) {
        connect(changeChip, &ChangeChip::SignalChanceChipVersion, this, &BurnDlg::SlotChanceChipVersion);
        changeChip->show();
    }
}

void BurnDlg::SlotChanceChipVersion(const QString &version) const
{
    Global::currentChipTypeId = Global::ChipTypeStringToId(version);
    Global::SaveCfg();
    Global::CloseApp(QAPP_EXIT_VALUE);
}

void BurnDlg::SlotShowAbout()
{
    if (aboutWin == nullptr) {
        aboutWin = new AboutWindow();
    }
    if (aboutWin != nullptr) {
        aboutWin->show();
    }
}

void BurnDlg::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);
    if (burnCtrl == nullptr) {
        return;
    }
    burnCtrl->RecordFile(QByteArray("Tool exited."));
    burnCtrl->CloseFile();
}

bool BurnDlg::IsSelectOtp(IMAGE_TYPE type) const
{
    if (Global::currentChipTypeId == ChipType::WIFI5GNB &&
        type == IMAGE_TYPE::IMAGE_TYPE_OTP) {
        return true;
    }
    return false;
}

void BurnDlg::SlotSetEnglish()
{
    QSettings cfg(Global::GetAppConfigPath() + "\\config_all_chip_type.ini", QSettings::IniFormat);
    cfg.setValue("AHHCHIPTYPECONFIG/TRANSLATE", 0);
    Sleep(SLEEP_TIME_500);
    Global::CloseApp(QAPP_EXIT_VALUE);
}

void BurnDlg::SlotSetChinese()
{
    QSettings cfg(Global::GetAppConfigPath() + "\\config_all_chip_type.ini", QSettings::IniFormat);
    cfg.setValue("AHHCHIPTYPECONFIG/TRANSLATE", 1);
    Sleep(SLEEP_TIME_500);
    Global::CloseApp(QAPP_EXIT_VALUE);
}

unsigned int BurnDlg::LoadFileConfigFromFileGetInfo(BIN_INFO &info, const QSettings &cfg, int index) const
{
    unsigned int ret = 1;
    QVariant ascReturnedFilePath = cfg.value(FILE_CONFIG + "/" + INI_FILE_PATH + QString::number(index));
    ret &= static_cast<unsigned int>(ascReturnedFilePath.isValid());
    info.path = ascReturnedFilePath.toString();
    QVariant ascReturnedFileName = cfg.value(FILE_CONFIG + "/" + INI_FILE_NAME + QString::number(index));
    ret &= static_cast<unsigned int>(ascReturnedFileName.isValid());
    info.fileName = ascReturnedFileName.toString();
    QVariant ascReturnedFileIndex = cfg.value(FILE_CONFIG + "/" + INI_FILE_INDEX + QString::number(index));
    ret &= static_cast<unsigned int>(ascReturnedFileIndex.isValid());
    info.fileIndex = ascReturnedFileIndex.toString();
    QVariant ascReturnedFileSize = cfg.value(FILE_CONFIG + "/" + INI_FILE_SIZE + QString::number(index));
    ret &= static_cast<unsigned int>(ascReturnedFileSize.isValid());
    info.fileSize = ascReturnedFileSize.toString();
    QVariant ascReturnedBurnAddr = cfg.value(FILE_CONFIG + "/" + INI_BURN_ADDR + QString::number(index));
    ret &= static_cast<unsigned int>(ascReturnedBurnAddr.isValid());
    info.burnAddr = ascReturnedBurnAddr.toString();
    QVariant ascReturnedBurnSize = cfg.value(FILE_CONFIG + "/" + INI_BURN_SIZE + QString::number(index));
    ret &= static_cast<unsigned int>(ascReturnedBurnSize.isValid());
    info.burnSize = ascReturnedBurnSize.toString();
    QVariant ascReturnedFileType = cfg.value(FILE_CONFIG + "/" + INI_FILE_TYPE + QString::number(index));
    ret &= static_cast<unsigned int>(ascReturnedFileType.isValid());
    info.type = static_cast<IMAGE_TYPE>(ascReturnedFileType.toInt());
    return ret;
}

void BurnDlg::CreateNewFwpkgFile(QString burnfilePath)
{
    QString newFileName = QFileDialog::getSaveFileName(this, stringClass.GetCreateNewFile(), "", "*.fwpkg;;*.*");
    if (newFileName.isEmpty()) {
        return;
    }
    if (!DataConvertor::CreateNewFwpkgFile(binModel->GetMapBinFileInfo(), newFileName, burnfilePath)) {
        return;
    }
    QMessageBox::information(this, "BurnTool", tr("Create new fwpkg file success."));
}

void BurnDlg::SaveSpiltFwpkgFile(QString burnfilePath)
{
    QString dirName = QFileDialog::getExistingDirectory(this, tr("Select save file directory"), "",
        QFileDialog::ShowDirsOnly);
    if (dirName.isEmpty()) {
        return;
    }
    if (!DataConvertor::SaveSpiltFwpkgFile(binModel->GetMapBinFileInfo(), dirName, burnfilePath)) {
        return;
    }
    QMessageBox::information(this, "BurnTool", tr("Save spilt file success."));
}

}

